package com.topisv.tms.service.stock.instorageNew;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.hibernate.ejb.criteria.predicate.ComparisonPredicate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.topisv.tms.entity.AreaGroup;
import com.topisv.tms.entity.Customers;
import com.topisv.tms.entity.User;
import com.topisv.tms.entity.lpn.LPN;
import com.topisv.tms.entity.receiptDetail.ReceiptDetail;
import com.topisv.tms.entity.stock.CusStock;
import com.topisv.tms.entity.stock.instorage.InstorageBill;
import com.topisv.tms.entity.stock.instorage.InstorageCountTask;
import com.topisv.tms.entity.stock.instorage.InstorageInfo;
import com.topisv.tms.entity.stock.instorage.InstorageLog;
import com.topisv.tms.entity.stock.instorage.InstorageUpDispatchSubTask;
import com.topisv.tms.entity.stock.instorage.InstorageUpSubTaskItem;
import com.topisv.tms.entity.stock.instorage.pre.InstorageBillPre;
import com.topisv.tms.entity.work.ExceptionOrder.ExceptionOrder;
import com.topisv.tms.exception.ErrorCode;
import com.topisv.tms.exception.PaiUException;
import com.topisv.tms.repository.AreaGroupDao;
import com.topisv.tms.repository.CustomersDao;
import com.topisv.tms.repository.UserDao;
import com.topisv.tms.repository.lpn.LPNDao;
import com.topisv.tms.repository.stock.CusStockDao;
import com.topisv.tms.repository.stock.instorage.InstorageInfoDao;
import com.topisv.tms.repository.stock.instorage.InstorageLogDao;
import com.topisv.tms.repository.stock.instorageNew.InstorageBillNewDao;
import com.topisv.tms.repository.stock.instorageNew.ReceiptDetailDao;
import com.topisv.tms.repository.stock.preInstorage.InstorageBillItemPreDao;
import com.topisv.tms.repository.stock.preInstorage.InstorageBillPreDao;
import com.topisv.tms.repository.work.ExceptionOrder.ExceptionOrderDao;
import com.topisv.tms.rest.qimen.qmsend.QmRequestSender;
import com.topisv.tms.rest.qimen.qmservice.EntryOrderConfirmService;
import com.topisv.tms.service.account.ShiroDbRealm.ShiroUser;
import com.topisv.tms.service.base.BaseService;
import com.topisv.tms.service.vo.PrinterStyleType;
import com.topisv.tms.utils.PrintModelUtil;
import com.topisv.tms.utils.PubUtil;
import com.topisv.tms.utils.enums.PYOrderType;

/**
 * 入库单_service
 * 
 * @author ch
 *
 */
@Component
@Transactional(readOnly = true)
public class InstorageBillNewService extends BaseService {
	protected Logger logger = LoggerFactory.getLogger(getClass());
	@Autowired
	private InstorageBillNewDao instorageBillNewDao;
	@Autowired
	private ReceiptDetailDao receiptDetailDao;
	@Autowired
	private CustomersDao customersDao;
	@Autowired
	private AreaGroupDao areagroupDao;
	@Autowired
	private UserDao userDao;
	@Autowired
	private InstorageBillPreDao instorageBillPreDao;
	@Autowired
	private InstorageBillItemPreDao instorageBillItemPreDao;
	@Autowired
	private CusStockDao cusStockDao;
	@Autowired
	private AreaGroupDao areaGroupDao;
	@Autowired
	private InstorageInfoDao instorageInfoDao;
	@Autowired
	private ExceptionOrderDao exceptionOrderDao;
	@Autowired
	private InstorageLogDao instorageLogDao;
	@Autowired
	private LPNDao lpnDao;
	@Autowired
	private InstorageScanService instorageScanService;
	@Resource(type = EntryOrderConfirmService.class)
	private QmRequestSender<Map<Object, Object>> entryOrderConfirmService;
	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	/**
	 * 分页查询
	 * 
	 * @param param
	 * @return
	 */
	public Page<InstorageBill> loadPageByParam(Map<String, Object> param, int pageNumber, int pageSize) {
		try {
			// 根据客户单号查询
			if (StringUtils.isNotBlank((String) param.get("customerOrderNo"))) {
				List<InstorageBillPre> pres = instorageBillPreDao.findBycustomerOrderNo((String) param.get("customerOrderNo"));
				StringBuffer nos = new StringBuffer();
				for (InstorageBillPre instorageBillPre : pres) {
					nos.append(instorageBillPre.getBillCode() + ":");
				}
				param.put("customerOrderNo", nos.toString().substring(0, nos.length() - 1));
			}

			PageRequest pageRequest = new PageRequest(pageNumber - 1, pageSize, new Sort(Direction.DESC, "createTime"));
			Specification<InstorageBill> spec = this.getWhereClause(param);

			Page<InstorageBill> page = this.instorageBillNewDao.findAll(spec, pageRequest);
			List<InstorageBill> billList = page.getContent();
			for (InstorageBill bill : billList) {
				this.setDetail(bill);
			}
			return page;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;

	}

	/**
	 * 查询条件封装
	 * 
	 * @param param
	 * @return
	 */
	private Specification<InstorageBill> getWhereClause(final Map<String, Object> param) {

		return new Specification<InstorageBill>() {

			@Override
			public Predicate toPredicate(Root<InstorageBill> r, CriteriaQuery<?> q, CriteriaBuilder cb) {
				Predicate pre = cb.conjunction();
				ShiroUser curUser = (ShiroUser) SecurityUtils.getSubject().getPrincipal();

				try {

					// 根据客户单号查询，直接返回
					String customerOrderNo = (String) param.get("customerOrderNo");
					if (StringUtils.isNotBlank(customerOrderNo)) {
						String[] customersSplit = customerOrderNo.split(":");
						ComparisonPredicate[] customersArray = new ComparisonPredicate[customersSplit.length];
						int j = 0;
						for (String _customerOrderNo : customersSplit) {
							customersArray[j] = (ComparisonPredicate) cb.equal(r.get("aboutCode"), _customerOrderNo);
							j++;
						}
						pre.getExpressions().add(cb.or(customersArray));
						return pre;
					}

					String customerCode = (String) param.get("customerCode");
					if (StringUtils.isNotBlank(customerCode)) {
						pre.getExpressions().add(cb.equal(r.<String> get("customerCode"), customerCode));
					} else {
						String customers = curUser.customers;
						if (StringUtils.isNotBlank(customers)) {
							String[] customersSplit = customers.split(":");
							ComparisonPredicate[] customersArray = new ComparisonPredicate[customersSplit.length];
							int j = 0;
							for (String _customers : customersSplit) {
								customersArray[j] = (ComparisonPredicate) cb.equal(r.get("customerCode"), _customers);
								j++;
							}
							pre.getExpressions().add(cb.or(customersArray));
						}
					}

					String warehouseCode = (String) param.get("warehouseCode");
					if (StringUtils.isNotEmpty(warehouseCode)) {
						pre.getExpressions().add(cb.equal(r.<String> get("inwarehouseCode"), warehouseCode));
					} else {
						String areagroups = curUser.areagroups;
						if (StringUtils.isNotBlank(areagroups)) {
							String[] areagroupSplit = areagroups.split(":");
							ComparisonPredicate[] areagroupArray = new ComparisonPredicate[areagroupSplit.length];
							int j = 0;
							for (String _areagroup : areagroupSplit) {
								areagroupArray[j] = (ComparisonPredicate) cb.equal(r.get("inwarehouseCode"), _areagroup);
								j++;
							}
							pre.getExpressions().add(cb.or(areagroupArray));
						}

					}
					DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
					String fromDateStr = (String) param.get("fromDate");
					if (StringUtils.isNotBlank(fromDateStr)) {
						Date fromDate = df.parse(fromDateStr + " 00:00:00");
						pre.getExpressions().add(cb.greaterThan(r.<Date> get("createTime"), fromDate));
					}

					String toDateStr = (String) param.get("toDate");
					if (StringUtils.isNotBlank(toDateStr)) {
						Date toDate = df.parse(toDateStr + " 23:59:59");
						pre.getExpressions().add(cb.lessThan(r.<Date> get("createTime"), toDate));
					}

					String billCode = (String) param.get("billCode");
					if (StringUtils.isNotEmpty(billCode)) {
						pre.getExpressions().add(cb.equal(r.get("billCode"), billCode));
					}
					String newstatus = (String) param.get("newstatus");
					if (StringUtils.isNotEmpty(newstatus)) {
						pre.getExpressions().add(cb.equal(r.get("newstatus"), newstatus));
					} else {
						pre.getExpressions().add(cb.notEqual(r.get("newstatus"), "-1"));
					}

				} catch (Exception e) {
				}

				return pre;
			}
		};
	}

	/**
	 * 设置入库单详细数据
	 * 
	 * @param instorageBillList
	 */
	private void setDetail(InstorageBill bill) {
		// 商家
		String customerCode = bill.getCustomerCode();
		Customers customer = this.customersDao.findByCustomerCode(customerCode);
		bill.setCustomer(customer);

		// 入库仓库
		String inwarehouseCode = bill.getInwarehouseCode();
		AreaGroup inwarehouse = this.areagroupDao.findByGroupCode(inwarehouseCode);
		bill.setInwarehouse(inwarehouse);

		// 出库仓库
		String outwarehouseCode = bill.getOutwarehouseCode();
		AreaGroup outwarehouse = this.areagroupDao.findByGroupCode(outwarehouseCode);
		bill.setOutwarehouse(outwarehouse);

		// 创建人
		String createrUuid = bill.getCreaterUuid();
		User creater = this.userDao.findByJobuuid(createrUuid);
		bill.setCreater(creater);

		// 入库预约单ID或美的的返仓入库单
		if (PYOrderType.PRE_ORDER.getType().equals(bill.getBillType()) || PYOrderType.RETURN_ORDER.getType().equals(bill.getBillType())) {
			InstorageBillPre preBill = this.instorageBillPreDao.findByBillCode(bill.getAboutCode());
			if (preBill != null) {
				preBill.setBillItem(instorageBillItemPreDao.query(preBill.getId()));
			}
			bill.setPreBill(preBill);
		}

	}

	//
	public InstorageBill loadById(Long billId) {
		return this.instorageBillNewDao.findOne(billId);
	}

	/**
	 * 查询入库单
	 * 
	 * @param billCode
	 * @return
	 */
	public InstorageBill loadBillByCode(String billCode) {
		InstorageBill inBill = this.instorageBillNewDao.loadBillByCode(billCode);
		this.setDetail(inBill);
		return inBill;
	}

	/**
	 * 保存收货明细
	 * 
	 * @param param
	 * @throws Exception
	 */
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public void createNewReceiptDetail(HashMap<String, Object> param) throws Exception {
		try {
			InstorageBill bill = (InstorageBill) param.get("instorageBill");
			ReceiptDetail rd = new ReceiptDetail();
			rd.setBillCode(bill.getBillCode());
			rd.setCustomerCode(bill.getCustomerCode());
			rd.setWarehouseCode(bill.getInwarehouseCode());
			rd.setLpnNo(String.valueOf(param.get("lpnNum")));
			rd.setSku(String.valueOf(param.get("sku")));
			rd.setBatchCode(String.valueOf(param.get("batchCode") == null ? "" : param.get("batchCode")));
			rd.setProductDate(String.valueOf(param.get("productDate") == null ? "" : param.get("productDate")));
			rd.setExpireDate(String.valueOf(param.get("expireDate") == null ? "" : param.get("expireDate")));
			rd.setSkuName(String.valueOf(param.get("skuName")));
			rd.setCountNum(Integer.valueOf(String.valueOf(param.get("num"))));
			rd.setUnUpNum(Integer.valueOf(String.valueOf(param.get("num"))));
			rd.setUpNum(0);
			rd.setStatus("0");
			rd.setCreateTime(new Date());
			rd.setCreator(bill.getCreaterUuid());
			rd.setErrorFlag(String.valueOf(param.get("errorflag")));
			rd.setLpnUpdateTime(new Date());
			this.receiptDetailDao.save(rd);
		} catch (Exception e) {
			throw e;
		}

	}

	/**
	 * 收货的入库日志
	 * 
	 * @param param
	 * @throws Exception
	 */
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public void saveInstorageLog(String billCode, ShiroUser curUser, String lpnNum, String skuName, int num, String flag) throws Exception {
		try {
			InstorageLog log = new InstorageLog();
			log.setBillCode(billCode);
			log.setWorkerUuid(curUser.jobuuid);
			log.setInfo(curUser.realname + "边收边上架中收货:" + lpnNum + "收了" + skuName + "(" + num + ")");
			log.setWorkTime(new Date());
			log.setWorkType(flag);
			this.instorageLogDao.save(log);
		} catch (Exception e) {
			throw e;
		}

	}

	/**
	 * 收货的入库日志
	 * 
	 * @param param
	 * @throws Exception
	 */
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public void saveInstorageLog(String billCode, User curUser, String lpnNum, String skuName, int num, String flag) throws Exception {
		try {
			InstorageLog log = new InstorageLog();
			log.setBillCode(billCode);
			log.setWorkerUuid(curUser.getJobuuid());
			log.setInfo(curUser.getRealname() + "边收边上架中收货:" + lpnNum + "收了" + skuName + "(" + num + ")");
			log.setWorkTime(new Date());
			log.setWorkType(flag);
			this.instorageLogDao.save(log);
		} catch (Exception e) {
			throw e;
		}

	}

	/**
	 * 修改入库单的newstatus状态
	 * 
	 * @param billCode
	 * @param status
	 */

	@Transactional(readOnly = false)
	public void updateInstorageBillNewStatus(String billCode, String status) {
		this.instorageBillNewDao.updateNewStatus(billCode, status);
	}

	/**
	 * 修改入库单的status状态
	 * 
	 * @param billCode
	 * @param status
	 */
	@Transactional(readOnly = false)
	public void updateInstorageBillStatus(String billCode) {
		this.instorageBillNewDao.updateStatus(billCode, "-1");
	}

	/**
	 * 更改收货明细的打印状态
	 */
	@Transactional(readOnly = false)
	public void updateReceiptDetailPrintFlag(List<Long> idList) {
		this.receiptDetailDao.updateReceiptDetailPrintFlag(idList);
	}

	/**
	 * 根据入库单跟LPN查询所有的收货明细
	 * 
	 * @param billCode
	 * @param status
	 */
	public List<ReceiptDetail> getUnUpDetailByLPN(String billCode, String lpn) {
		return this.receiptDetailDao.getUnUpDetailByLPN(billCode, lpn);
	}

	public List<ReceiptDetail> getUnUpDetailByLPN(String lpn) {
		return this.receiptDetailDao.getUnUpDetailByLPN(lpn);
	}

	/**
	 * 根据入库单跟LPN查询已上架的收货明细
	 * 
	 * @param billCode
	 * @param lpn
	 * @return
	 */
	public List<ReceiptDetail> getUpDetailByLPN(String billCode, String lpn) {
		return this.receiptDetailDao.getUpDetailByLPN(billCode, lpn);
	}

	public List<ReceiptDetail> getUpDetailByLPN(String lpn) {
		return this.receiptDetailDao.getUpDetailByLPN(lpn);
	}

	/**
	 * 检查新库位
	 * 
	 * @param stockCode
	 * @return
	 */
	public List<CusStock> checkUpStorage(String stockCode) {
		return this.cusStockDao.loadByStockCode(stockCode);
	}

	/**
	 * 完成上架
	 */
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public String finishUpShelf(String billCode, String lpn, String sku, String batchCode, String productDate, String expireDate, String upStorage, String num, String errorFlag) throws Exception {
		try {
			String msg = "finishing";
			// List<CusStock> cusStockList=this.checkUpStorage(upStorage);
			// if(cusStockList.size()>0){
			// return "sotrageExist";
			// }
			
			//EditBy yinglei_lian 暂时取消批次和有效期管理
			//ReceiptDetail rd = this.receiptDetailDao.loadByReceiptDetailNew(billCode, lpn, sku, batchCode, productDate, expireDate);
			ReceiptDetail rd = this.receiptDetailDao.loadByReceiptDetail(billCode, lpn, sku);
			if (rd == null) {
				return "finish";
			}
			InstorageBill bill = this.instorageBillNewDao.loadBillByCode(billCode);
			if ("6".equals(bill.getNewstatus())) {
				return "uped";
			}
			if ("7".equals(bill.getStatus())) {
				return "isEmpty";
			}
			// 已取消的不能领取
			if ("8".equals(bill.getStatus())) {
				return ErrorCode.ORDER_CANCELED_ERROR.getCode();
			}
			String errorFlagName = "";
			if ("error".equals(errorFlag)) {
				errorFlagName = "破损";
			} else if ("noterror".equals(errorFlag)) {
				errorFlagName = "完好";
			}
			int countNum = rd.getCountNum();
			int unUnpNum = rd.getUnUpNum();
			int upNum = rd.getUpNum();
			int inputNum = Integer.valueOf(num);
			if (unUnpNum > inputNum) {
				rd.setStatus("1");
			} else if (unUnpNum == inputNum) {
				rd.setStatus("2");
				// 该入库单号、LPN中除了sku之外还没有上架的的记录
				List<ReceiptDetail> otherSkuReceiptDetailList = this.receiptDetailDao.getLPNOtherSkuUnUpNew(billCode, lpn, sku, batchCode, productDate, expireDate);
				if (otherSkuReceiptDetailList.size() == 0) {
					// 释放LPN
					LPN lpnEnity = this.lpnDao.loadLPN(bill.getInwarehouseCode(), lpn);
					lpnEnity.setStatus("0");
					lpnEnity.setOrderNo("");
					this.lpnDao.save(lpnEnity);
					rd.setLpnUpdateTime(new Date());
				}
			} else {
				return "numOver";
			}
			rd.setUpNum((upNum + inputNum));
			rd.setUnUpNum((unUnpNum - inputNum));
			rd.setStockCode(rd.getStockCode() == null ? upStorage + "(" + inputNum + ":" + errorFlagName + ")" : rd.getStockCode() + ":" + upStorage + "(" + inputNum + ":" + errorFlagName + ")");
			this.receiptDetailDao.save(rd);
			// 查询该入库单中是否还有其他LPN号没有完全上架
			List<Map<String, Object>> receiptDetailUnUpCountList = this.instorageScanService.getReceiptDetailUnUpCountByBillCode(bill.getBillCode());
			int flag = 1;
			if (receiptDetailUnUpCountList.size() == 0) {
				flag = 2;
			}
			// 修改入库单状态newstatus 0：新建 1:部分收货未上架 2:部分收货部分上架 3:部分收货完全上架 4:完全收货未上架
			// 5:完全收货部分上架 6:完全收货完全上架 7:已关闭 8:已取消
			if (bill.getNewstatus().equals("1") || bill.getNewstatus().equals("2")) {
				bill.setNewstatus(flag == 1 ? "2" : "3");
			} else if (bill.getNewstatus().equals("4") || bill.getNewstatus().equals("5")) {// 部分收货部分上架
				bill.setNewstatus(flag == 1 ? "5" : "6");
			}
			this.instorageBillNewDao.save(bill);

			// 创建库存数据
			Date now = new Date();
			ShiroUser curUser = getShiroUser();
			User worker = this.userDao.findByJobuuid(curUser.getJobuuid());

			// AddBy yinglei_lian 2016.09.28 判断该库位中是否已经存在商品的并且数量大于0
			// this.cusStockDao.LoadOtherStock(bill.getCustomerCode(),
			// bill.getInwarehouseCode(), upStorage, upStorage, sku);
			CusStock otherCusStock = checkUpToOtherStock(bill.getCustomerCode(), bill.getInwarehouseCode(), upStorage, upStorage, sku, batchCode, productDate, expireDate);
			if (otherCusStock != null)
				throw new PaiUException(ErrorCode.REDO_INSTORAGE_UP_DISPATCH_TASK, new String[] { sku + "SKU、批次号、生产日期、过期日期不匹配" });

			CusStock stock = null;
			List<CusStock> stockList = this.cusStockDao.loadStockNew(bill.getCustomerCode(), bill.getInwarehouseCode(), upStorage, upStorage);

			for (CusStock stock2 : stockList) {
				//if (!(stock2.getSku().equals(sku)) || !((stock2.getBatchCode() == null ? "" : stock2.getBatchCode()).equals((batchCode == null ? "" : batchCode))) || !((stock2.getProductDate() == null ? "" : stock2.getProductDate()).equals((productDate == null ? "" : productDate))) || !((stock2.getExpireDate() == null ? "" : stock2.getExpireDate()).equals((expireDate == null ? "" : expireDate)))) {
				if (!(stock2.getSku().equals(sku)) ) {
//					if ((stock2.getSalesNum() + stock2.getUnusedNum() + stock2.getOrderNum() + stock2.getLockedNum() + stock2.getTransportNum() + stock2.getAirNum()) != 0) {
//						throw new PaiUException(ErrorCode.REDO_INSTORAGE_UP_DISPATCH_TASK, new String[] { stock2.getSku() + "SKU、批次号、生产日期、过期日期不匹配" });
//					}
				} else {
					stock = stock2;
					break;
				}
			}

			if (stock == null) {
				stock = new CusStock();
				stock.setBoxCode(upStorage);
				stock.setSku(sku);
				stock.setBatchCode(batchCode == "" ? null : batchCode);
				stock.setProductDate(productDate == "" ? null : productDate);
				stock.setExpireDate(expireDate == "" ? null : expireDate);
				stock.setCustomerCode(bill.getCustomerCode());
				Customers customer = this.customersDao.findByCustomerCode(bill.getCustomerCode());
				stock.setCustomer(customer);
				AreaGroup warehouse = this.areaGroupDao.findByGroupCode(bill.getInwarehouseCode());
				stock.setWarehouse(warehouse);
				stock.setWarehouseCode(bill.getInwarehouseCode());
				stock.setStockCode(upStorage);
				stock.setUnusedNum(0);
				stock.setOrderNum(0);
				stock.setLockedNum(0);
				stock.setTransportNum(0);
				stock.setAirNum(0);
				stock.setStockType("1");

				stock.setSalesNum(0);
			}/*
			 * else{ if(!(stock.getSku().equals(sku)) || !((stock.getBatchCode()
			 * == null ? "" : stock.getBatchCode()).equals(batchCode)) ||
			 * !((stock.getProductDate() == null ? "" :
			 * stock.getProductDate()).equals(productDate)) ||
			 * !((stock.getExpireDate() == null ? "" :
			 * stock.getExpireDate()).equals(expireDate))){ //return "notMatch";
			 * throw new
			 * PaiUException(ErrorCode.REDO_INSTORAGE_UP_DISPATCH_TASK, new
			 * String[] {stock.getSku() + "SKU、批次号、生产日期、过期日期不匹配"}); } }
			 */

			if ("error".equals(errorFlag)) {
				stock.setUnusedNum(stock.getUnusedNum() + inputNum);
			} else if ("noterror".equals(errorFlag)) {
				stock.setSalesNum(stock.getSalesNum() + inputNum);
			}
			stock.setLastmodifyTime(now);
			stock.setLastopetator(worker);
			this.cusStockDao.save(stock);

			// 如果是完全收货完全上架，自动发送奇门接口
			if (bill.getNewstatus().equals("6")) {
				ExceptionOrder eo = exceptionOrderDao.loadByOrderno(bill.getAboutCode());
				if (eo == null && !"allot".equals(bill.getBillType())) {
					// 入库单类型 (customer. 采购入库 allot.调拨入库 returnOrder：退回入库
					// preOrder: 预约入库)
					logger.info("完全收货完全上架不是取消订单上架 正常发送奇门流水。");
					Map<Object, Object> params = new HashMap<Object, Object>();
					params.put("billType", bill.getBillType());
					params.put("status", bill.getStatus());
					params.put("newstatus", bill.getNewstatus());
					params.put("preCode", bill.getAboutCode());
					entryOrderConfirmService.send(params, bill.getCustomerCode());
				} else {
					logger.info("完全收货完全上架取消单上架不发送奇门流水。");
				}
				bill.setNewstatus("7");
				this.instorageBillNewDao.save(bill);
			}

			// 入库记录
			InstorageInfo info = this.instorageInfoDao.loadByBillCodeAndLpnAndSkuAndFlag(bill.getBillCode(), lpn, sku, errorFlag);
			if (info == null) {
				info = new InstorageInfo();
				info.setCustomerCode(bill.getCustomerCode());
				info.setWarehouseCode(bill.getInwarehouseCode());
				info.setBillCode(bill.getBillCode());
				info.setUptaskCode(lpn);
				info.setSku(sku);
				info.setBillType(bill.getBillType());
				info.setOpeTime(now);
				info.setNum(0);
				info.setErrorFlag(errorFlag);
			}
			info.setNum(info.getNum() + inputNum);
			this.instorageInfoDao.save(info);

			// 如果是异常单（取消单/退回件）入库，修改异常单状态为：已入库。
			String billType = bill.getBillType();
			String aboutCode = bill.getAboutCode();
			if ("cancelOrder".equals(billType) || "returnOrder".equals(billType)) {
				ExceptionOrder exceptionOrder = this.exceptionOrderDao.loadByOrderno(aboutCode);
				if (exceptionOrder != null) {
					exceptionOrder.setBackStatus("in");
					this.exceptionOrderDao.save(exceptionOrder);
				}
			}
			// //写入库日志
			InstorageLog log = new InstorageLog();
			log.setBillCode(bill.getBillCode());
			log.setInfo(worker.getRealname() + "边收边上架 上架:" + lpn + "上架" + sku + "(" + num + ")" + errorFlagName);
			log.setWorkerUuid(worker.getJobuuid());
			log.setWorkTime(now);
			log.setWorkType(bill.getNewstatus());
			this.instorageLogDao.save(log);

			return msg;
		} catch (Exception e) {

			e.printStackTrace();
			throw e;
		}
	}

	/**
	 * 检查to的库位上是否有其他商品 AddBy yinglei_lian 2016.09.29
	 * 
	 * @param to
	 * @return
	 */
	private CusStock checkUpToOtherStock(String customerCode, String warehouseCode, String stockCode, String boxCode, String sku, String batchCode, String productDate, String expireDate) {
//		List<CusStock> cusStocks = cusStockDao.LoadOtherStock(customerCode, warehouseCode, stockCode, boxCode, sku);// 判断是否有其他商品
//		if (cusStocks != null && cusStocks.size()>0)
//			return cusStocks.get(0);// 有其他商品 不能移库
		// 有没相同商品 但是批次、时间不同的商品
		if ((PubUtil.isNotEmpty(batchCode) || PubUtil.isNotEmpty(productDate) || PubUtil.isNotEmpty(expireDate))) {// 有有效期管理
			List<CusStock> stockList = this.cusStockDao.loadStockNew(customerCode, warehouseCode, stockCode, boxCode);
			for (CusStock stock2 : stockList) {
				if ((stock2.getSku().equals(sku)) && (!(stock2.getBatchCode() == null ? "" : stock2.getBatchCode()).equals(batchCode == null ? "" : batchCode)) || !((stock2.getProductDate() == null ? "" : stock2.getProductDate()).equals(productDate == null ? "" : productDate)) || !((stock2.getExpireDate() == null ? "" : stock2.getExpireDate()).equals(expireDate == null ? "" : expireDate))) {
					if ((stock2.getSalesNum() + stock2.getUnusedNum() + stock2.getOrderNum() + stock2.getLockedNum() + stock2.getTransportNum() + stock2.getAirNum()) != 0) {
						return stock2;
					}
				}
			}
		}
		return null;
	}

	/**
	 * 完成上架
	 */
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public String finishUpShelf(String billCode, String lpn, String sku, String upStorage, String num, String errorFlag, String jobuuid) throws Exception {
		try {
			String msg = "finishing";
			// List<CusStock> cusStockList=this.checkUpStorage(upStorage);
			// if(cusStockList.size()>0){
			// return "sotrageExist";
			// }
			ReceiptDetail rd = this.receiptDetailDao.loadByReceiptDetail(billCode, lpn, sku);
			if (rd == null) {
				return "finish";
			}
			InstorageBill bill = this.instorageBillNewDao.loadBillByCode(billCode);
			if ("6".equals(bill.getNewstatus())) {
				return "uped";
			}
			if ("7".equals(bill.getStatus())) {
				return "isEmpty";
			}
			// 已取消的不能领取
			if ("8".equals(bill.getStatus())) {
				return ErrorCode.ORDER_CANCELED_ERROR.getCode();
			}
			String errorFlagName = "";
			if ("error".equals(errorFlag)) {
				errorFlagName = "破损";
			} else if ("noterror".equals(errorFlag)) {
				errorFlagName = "完好";
			}
			int countNum = rd.getCountNum();
			int unUnpNum = rd.getUnUpNum();
			int upNum = rd.getUpNum();
			int inputNum = Integer.valueOf(num);
			if (unUnpNum > inputNum) {
				rd.setStatus("1");
			} else if (unUnpNum == inputNum) {
				rd.setStatus("2");
				// 该入库单号、LPN中除了sku之外还没有上架的的记录
				List<ReceiptDetail> otherSkuReceiptDetailList = this.receiptDetailDao.getLPNOtherSkuUnUp(billCode, lpn, sku);
				if (otherSkuReceiptDetailList.size() == 0) {
					// 释放LPN
					LPN lpnEnity = this.lpnDao.loadLPN(bill.getInwarehouseCode(), lpn);
					lpnEnity.setStatus("0");
					lpnEnity.setOrderNo("");
					this.lpnDao.save(lpnEnity);
					rd.setLpnUpdateTime(new Date());
				}
			} else {
				return "numOver";
			}
			rd.setUpNum((upNum + inputNum));
			rd.setUnUpNum((unUnpNum - inputNum));
			rd.setStockCode(rd.getStockCode() == null ? upStorage + "(" + inputNum + ":" + errorFlagName + ")" : rd.getStockCode() + ":" + upStorage + "(" + inputNum + ":" + errorFlagName + ")");
			this.receiptDetailDao.save(rd);
			// 查询该入库单中是否还有其他LPN号没有完全上架
			List<Map<String, Object>> receiptDetailUnUpCountList = this.instorageScanService.getReceiptDetailUnUpCountByBillCode(bill.getBillCode());
			int flag = 1;
			if (receiptDetailUnUpCountList.size() == 0) {
				flag = 2;
			}
			// 修改入库单状态newstatus 0：新建 1:部分收货未上架 2:部分收货部分上架 3:部分收货完全上架 4:完全收货未上架
			// 5:完全收货部分上架 6:完全收货完全上架 7:已关闭 8:已取消
			if (bill.getNewstatus().equals("1") || bill.getNewstatus().equals("2")) {
				bill.setNewstatus(flag == 1 ? "2" : "3");
			} else if (bill.getNewstatus().equals("4") || bill.getNewstatus().equals("5")) {// 部分收货部分上架
				bill.setNewstatus(flag == 1 ? "5" : "6");
			}
			this.instorageBillNewDao.save(bill);

			// 创建库存数据
			Date now = new Date();
			ShiroUser curUser = getShiroUser();
			User worker = this.userDao.findByJobuuid(jobuuid);// this.userDao.findByJobuuid(curUser.getJobuuid());
			CusStock stock = this.cusStockDao.loadStock(bill.getCustomerCode(), bill.getInwarehouseCode(), upStorage, upStorage, sku);
			if (stock == null) {
				stock = new CusStock();
				stock.setBoxCode(upStorage);
				stock.setSku(sku);
				stock.setCustomerCode(bill.getCustomerCode());
				Customers customer = this.customersDao.findByCustomerCode(bill.getCustomerCode());
				stock.setCustomer(customer);
				AreaGroup warehouse = this.areaGroupDao.findByGroupCode(bill.getInwarehouseCode());
				stock.setWarehouse(warehouse);
				stock.setWarehouseCode(bill.getInwarehouseCode());
				stock.setStockCode(upStorage);
				stock.setUnusedNum(0);
				stock.setOrderNum(0);
				stock.setLockedNum(0);
				stock.setTransportNum(0);
				stock.setAirNum(0);
				stock.setStockType("1");

				stock.setSalesNum(0);
			}
			if ("error".equals(errorFlag)) {
				stock.setUnusedNum(stock.getUnusedNum() + inputNum);
			} else if ("noterror".equals(errorFlag)) {
				stock.setSalesNum(stock.getSalesNum() + inputNum);
			}
			stock.setLastmodifyTime(now);
			stock.setLastopetator(worker);
			this.cusStockDao.save(stock);

			// 如果是完全收货完全上架，自动发送奇门接口
			if (bill.getNewstatus().equals("6")) {
				ExceptionOrder eo = exceptionOrderDao.loadByOrderno(bill.getAboutCode());
				if (eo == null && !"allot".equals(bill.getBillType())) {
					// 入库单类型 (customer. 采购入库 allot.调拨入库 returnOrder：退回入库
					// preOrder: 预约入库)
					logger.info("完全收货完全上架不是取消订单上架 正常发送奇门流水。");
					Map<Object, Object> params = new HashMap<Object, Object>();
					params.put("billType", bill.getBillType());
					params.put("status", bill.getStatus());
					params.put("newstatus", bill.getNewstatus());
					params.put("preCode", bill.getAboutCode());
					entryOrderConfirmService.send(params, bill.getCustomerCode());
				} else {
					logger.info("完全收货完全上架取消单上架不发送奇门流水。");
				}
				bill.setNewstatus("7");
				this.instorageBillNewDao.save(bill);
			}

			// 入库记录
			InstorageInfo info = this.instorageInfoDao.loadByBillCodeAndLpnAndSkuAndFlag(bill.getBillCode(), lpn, sku, errorFlag);
			if (info == null) {
				info = new InstorageInfo();
				info.setCustomerCode(bill.getCustomerCode());
				info.setWarehouseCode(bill.getInwarehouseCode());
				info.setBillCode(bill.getBillCode());
				info.setUptaskCode(lpn);
				info.setSku(sku);
				info.setBillType(bill.getBillType());
				info.setOpeTime(now);
				info.setNum(0);
				info.setErrorFlag(errorFlag);
			}
			info.setNum(info.getNum() + inputNum);
			this.instorageInfoDao.save(info);

			// 如果是异常单（取消单/退回件）入库，修改异常单状态为：已入库。
			String billType = bill.getBillType();
			String aboutCode = bill.getAboutCode();
			if ("cancelOrder".equals(billType) || "returnOrder".equals(billType)) {
				ExceptionOrder exceptionOrder = this.exceptionOrderDao.loadByOrderno(aboutCode);
				if (exceptionOrder != null) {
					exceptionOrder.setBackStatus("in");
					this.exceptionOrderDao.save(exceptionOrder);
				}
			}
			// //写入库日志
			InstorageLog log = new InstorageLog();
			log.setBillCode(bill.getBillCode());
			log.setInfo(worker.getRealname() + "边收边上架 上架:" + lpn + "上架" + sku + "(" + num + ")" + errorFlagName);
			log.setWorkerUuid(worker.getJobuuid());
			log.setWorkTime(now);
			log.setWorkType(bill.getNewstatus());
			this.instorageLogDao.save(log);

			return msg;
		} catch (Exception e) {
			throw e;
		}
	}

	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public String sendQiMen(InstorageBill bill) throws Exception {
		String msg = "success";
		try {
			ExceptionOrder eo = exceptionOrderDao.loadByOrderno(bill.getAboutCode());
			if (eo == null && !"allot".equals(bill.getBillType())) {
				// 入库单类型 (customer. 采购入库 allot.调拨入库 returnOrder：退回入库 preOrder:
				// 预约入库)
				logger.info("边收边上架不是取消订单上架 正常发送奇门流水。");
				Map<Object, Object> params = new HashMap<Object, Object>();
				params.put("billType", bill.getBillType());
				params.put("status", bill.getStatus());
				params.put("newstatus", bill.getNewstatus());
				params.put("preCode", bill.getAboutCode());
				entryOrderConfirmService.send(params, bill.getCustomerCode());

			} else {
				logger.info("边收边上架取消单上架不发送奇门流水。");
			}
			bill.setNewstatus("7");
			this.instorageBillNewDao.save(bill);

			ShiroUser curUser = getShiroUser();
			User worker = this.userDao.findByJobuuid(curUser.getJobuuid());
			InstorageLog log = new InstorageLog();
			log.setBillCode(bill.getBillCode());
			log.setInfo(worker.getRealname() + "边收边上架 关闭订单");
			log.setWorkerUuid(worker.getJobuuid());
			log.setWorkTime(new Date());
			log.setWorkType(bill.getNewstatus());
			this.instorageLogDao.save(log);

		} catch (Exception e) {
			msg = "error";
			logger.error("边收边上架QMSendError entryOrderConfirm : " + e);
			throw e;
		}
		return msg;
	}

	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public String cancalReceipt(Long id) throws Exception {
		String msg = "success";
		try {
			ReceiptDetail rd = this.receiptDetailDao.findOne(id);
			InstorageBill bill = this.instorageBillNewDao.loadBillByCode(rd.getBillCode());
			int countNum = rd.getCountNum();// 收货数量
			int unUpNum = rd.getUnUpNum(); // 未上架数量

			if ((countNum - unUpNum) > 0) {
				rd.setCountNum((countNum - unUpNum));
				rd.setUnUpNum(0);
				rd.setStatus("2");

			} else if ((countNum - unUpNum) == 0) {
				rd.setStatus("3");
			}

			// 该入库单号、LPN中除了sku之外还没有上架的的记录
			List<ReceiptDetail> otherSkuReceiptDetailList = this.receiptDetailDao.getLPNOtherSkuUnUp(rd.getBillCode(), rd.getLpnNo(), rd.getSku());
			if (otherSkuReceiptDetailList.size() == 0) {
				// 释放LPN
				LPN lpnEnity = this.lpnDao.loadLPN(rd.getWarehouseCode(), rd.getLpnNo());
				lpnEnity.setStatus("0");
				lpnEnity.setOrderNo("");
				this.lpnDao.save(lpnEnity);
				rd.setLpnUpdateTime(new Date());
			}
			this.receiptDetailDao.save(rd);
			// 查询该入库单中是否还有其他LPN号没有完全上架
			List<Map<String, Object>> receiptDetailUnUpCountList = this.instorageScanService.getReceiptDetailUnUpCountByBillCode(bill.getBillCode());
			if (receiptDetailUnUpCountList.size() > 0) {
				// 修改入库单状态newstatus 0：新建 1:部分收货未上架 2:部分收货部分上架 3:部分收货完全上架
				// 4:完全收货未上架 5:完全收货部分上架 6:完全收货完全上架 7:已关闭 8:已取消
				if (bill.getNewstatus().equals("5")) {// 完全收货部分上架
					bill.setNewstatus("2");// 部分收货部分上架
				}
				// bug 340 by zhangweize
				else if ("4".equals(bill.getNewstatus())) {// 完全收货未上架
					bill.setNewstatus("1");// 部分收货未上架
				}
			} else {
				if (bill.getNewstatus().equals("5")) {// 完全收货部分上架
					bill.setNewstatus("3");// 部分收货完全上架
				} else if (bill.getNewstatus().equals("1")) {
					bill.setNewstatus("0");
				} else if (bill.getNewstatus().equals("4")) {
					bill.setNewstatus("0");
				} else if (bill.getNewstatus().equals("2")) {
					bill.setNewstatus("3");
				}
			}
			this.instorageBillNewDao.save(bill);
			ShiroUser curUser = getShiroUser();
			User worker = this.userDao.findByJobuuid(curUser.getJobuuid());
			InstorageLog log = new InstorageLog();
			log.setBillCode(bill.getBillCode());
			log.setInfo(worker.getRealname() + "边收边上架 取消收货:" + rd.getLpnNo() + "取消" + rd.getSku() + "(" + unUpNum + ")");
			log.setWorkerUuid(worker.getJobuuid());
			log.setWorkTime(new Date());
			log.setWorkType(bill.getNewstatus());
			this.instorageLogDao.save(log);

		} catch (Exception e) {
			msg = "false";
			logger.error("边收边上架QMSendError entryOrderConfirm : " + e);
			throw e;
		}
		return msg;
	}

	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public List<InstorageBill> findAPPInstorageBill(Map<String, Object> param) {
		User curUser = this.userDao.findByJobuuid((String) param.get("workerUuid"));
		if (null == curUser) {
			return null;
		}
		Specification<InstorageBill> spec = getWhereClauseApp(param, curUser);
		List<InstorageBill> taskList = this.instorageBillNewDao.findAll(spec);
		for (InstorageBill item : taskList) {
			this.setDetail(item);
		}
		return taskList;
	}

	private Specification<InstorageBill> getWhereClauseApp(final Map<String, Object> param, final User curUser) {

		return new Specification<InstorageBill>() {

			@Override
			public Predicate toPredicate(Root<InstorageBill> r, CriteriaQuery<?> q, CriteriaBuilder cb) {
				Predicate pre = cb.conjunction();

				try {

					String customerCode = (String) param.get("customerCode");
					if (StringUtils.isNotBlank(customerCode)) {
						pre.getExpressions().add(cb.equal(r.<String> get("customerCode"), customerCode));
					} else {
						String customers = curUser.getCustomers();
						if (StringUtils.isNotBlank(customers)) {
							String[] customersSplit = customers.split(":");
							ComparisonPredicate[] customersArray = new ComparisonPredicate[customersSplit.length];
							int j = 0;
							for (String _customers : customersSplit) {
								customersArray[j] = (ComparisonPredicate) cb.equal(r.get("customerCode"), _customers);
								j++;
							}
							pre.getExpressions().add(cb.or(customersArray));
						}
					}

					String warehouseCode = (String) param.get("warehouseCode");
					if (StringUtils.isNotEmpty(warehouseCode)) {
						pre.getExpressions().add(cb.equal(r.<String> get("inwarehouseCode"), warehouseCode));
					} else {
						String areagroups = curUser.getAreagroups();
						if (StringUtils.isNotBlank(areagroups)) {
							String[] areagroupSplit = areagroups.split(":");
							ComparisonPredicate[] areagroupArray = new ComparisonPredicate[areagroupSplit.length];
							int j = 0;
							for (String _areagroup : areagroupSplit) {
								areagroupArray[j] = (ComparisonPredicate) cb.equal(r.get("inwarehouseCode"), _areagroup);
								j++;
							}
							pre.getExpressions().add(cb.or(areagroupArray));
						}

					}
					DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
					String fromDateStr = (String) param.get("fromDate");
					if (StringUtils.isNotBlank(fromDateStr)) {
						Date fromDate = df.parse(fromDateStr + " 00:00:00");
						pre.getExpressions().add(cb.greaterThan(r.<Date> get("createTime"), fromDate));
					}

					String toDateStr = (String) param.get("toDate");
					if (StringUtils.isNotBlank(toDateStr)) {
						Date toDate = df.parse(toDateStr + " 23:59:59");
						pre.getExpressions().add(cb.lessThan(r.<Date> get("createTime"), toDate));
					}

					String billCode = (String) param.get("billCode");
					if (StringUtils.isNotEmpty(billCode)) {
						pre.getExpressions().add(cb.equal(r.get("billCode"), billCode));
					}
					String newstatus = (String) param.get("newstatus");
					if (StringUtils.isNotEmpty(newstatus)) {
						pre.getExpressions().add(cb.equal(r.get("newstatus"), newstatus));
					} else {
						pre.getExpressions().add(cb.notEqual(r.get("newstatus"), "-1"));
					}

				} catch (Exception e) {
					return null;
				}

				return pre;
			}
		};
	}

	// public Object printLpnUpTask(String lpn) {
	// // TODO Auto-generated method stub
	// List<PrinterStyleType> rs = new ArrayList<PrinterStyleType>();
	// List<Map<String,Object>> tasks =
	// instorageScanService.getReceiptDetailSKUByLpn(lpn);
	// String content = PrintModelUtil.buildUpLpnTaskPrintContent(lpn,tasks);
	// PrinterStyleType style = new PrinterStyleType();
	// style.setContent(content);
	// style.setPrinterName(lpn);
	// rs.add(style);
	// return rs;
	// }
	/**
	 * 打印验收单
	 * 
	 * @param billCode
	 * @return
	 */
	public List<Map<String, Object>> printInstorageBillDetailForYS(String billCode) {
		String sql = "select b.bill_code as billCode,b.about_code as aboutCode,b.sku_code as skuCode,a.sku_name as skuName,IFNULL(a.spec,'') as spec,b.goods_num as goodsNum,b.countNum from edi_goods_sku a, " + "( " + " select c.bill_code,c.about_code,c.customer_code,c.inwarehouse_code,c.sku_code,c.goods_num,coalesce(d.countNum,0) as countNum from " + " (" + " select a.about_code ,a.inwarehouse_code,a.customer_code,a.bill_code,c.sku_code,c.goods_num " + " from instorage_bill a,instorage_bill_pre b,instorage_bill_item_pre c " + " where a.about_code=b.bill_code and b.id=c.bill_pre_id and a.bill_code='" + billCode + "'" + " )c " + " LEFT JOIN " + " (" + " select bill_code,customer_code,warehouse_code,sku,sum(count_num) as countNum" + " from tt_up_task " + "where bill_code='" + billCode
				+ "' and status<>'3' group by bill_code,customer_code,warehouse_code,sku" + ") d " + "on c.bill_code=d.bill_code and c.customer_code=d.customer_code and c.inwarehouse_code=d.warehouse_code and c.sku_code=d.sku " + ") b where a.customer_code=b.customer_code and a.sku_id=b.sku_code ";
		return jdbcTemplate.queryForList(sql);

	}

	public List<Map<String, Object>> getReceiptDetailByMaxDate(String billCode) {
		String sql = "select date_format(create_time,'%Y-%m-%d') as createTime from tt_up_task where bill_code='" + billCode + "' order by create_time desc limit 0,1 ";
		return jdbcTemplate.queryForList(sql);
	}

	/**
	 * 验收单次数
	 * 
	 * @param billCode
	 * @return
	 */
	public int updateInstorageBillPrintYsNum(String billCode) {
		String sql = "update instorage_bill set print_ysnum=print_ysnum+1 where bill_code='" + billCode + "'";
		return jdbcTemplate.update(sql);
	}

	/**
	 * 打印上架单
	 * 
	 * @param billCode
	 * @return
	 */
	public List<Map<String, Object>> printInstorageBillDetailForUp(String billCode) {
		String sql = "select b.sku as sku,a.sku_name as skuName,b.errorFlag,(b.countNum-b.upNum) as unUpNum,lpn_no as lpn " + "from edi_goods_sku a, " + " (" + " select bill_code,customer_code,warehouse_code,sku," + " case when error_flag='noterror' then '完好'" + " when error_flag='error'then '破损'" + " END AS errorFlag,sum(count_num) as countNum,sum(up_num) as upNum,lpn_no " + " from tt_up_task where bill_code='" + billCode + "' and status<>'3' " + " group by bill_code,bill_code,customer_code,warehouse_code,sku,lpn_no,error_flag " + ") b where a.customer_code=b.customer_code and a.sku_id=b.sku";
		return jdbcTemplate.queryForList(sql);
	}

	/**
	 * 上架单次数
	 * 
	 * @param billCode
	 * @return
	 */
	public int updateInstorageBillPrintSjNum(String billCode) {
		String sql = "update instorage_bill set print_sjnum=print_sjnum+1 where bill_code='" + billCode + "'";
		return jdbcTemplate.update(sql);
	}

	/**
	 * 确认收货打印上架单
	 * 
	 * @param billCode
	 * @return
	 */
	public List<Map<String, Object>> getReceiptDetailMaxDateByCodeAndLpn(String billCode, String lpn) {
		String sql = "select date_format(create_time,'%Y-%m-%d') as createTime from tt_up_task where bill_code='" + billCode + "' and lpn_no='" + lpn + "' order by create_time desc limit 0,1 ";
		return jdbcTemplate.queryForList(sql);
	}

	/**
	 * 获取sku批次信息
	 * 
	 * @param billCode
	 *            sku
	 * @return
	 */
	public List<Map<String, Object>> batchList(String billCode, String lpnNo, String sku) {
		String sql = "select distinct batch_code, product_date, expire_date" + " from tt_up_task where bill_code = '" + billCode + "' " + " and sku = '" + sku + "' " + " and lpn_no = '" + lpnNo + "' and un_up_num > 0 and status in ('0','1') order by product_date desc";
		return jdbcTemplate.queryForList(sql);
	}
}
